﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Data;
using System.Runtime.CompilerServices;
using System.Threading;

using Castle.Core.Logging;

using InfoGenerateSystem.Core.Utils;
using InfoGenerateSystem.Domain;
using InfoGenerateSystem.Persistence.IDao;
using InfoGenerateSystem.Component;
using InfoGenerateSystem.Service.Interfaces;

namespace InfoGenerateSystem.Service.Implements
{
    /// <summary>
    /// 根据装载的标签生成Excel并写入数据库服务类
    /// 
    /// 创建人:     王昊
    /// 创建时间:   2009-05-04
    /// 
    /// </summary>
    public class ExcelToDatabase : AbstractConfigService, IExcelToDatabase
    {
        private IGenericDao _dao = ServiceHelper.GetService(typeof(IGenericDao)) as IGenericDao;
        private ILogger _log = ServiceHelper.GetService(typeof(ILogger)) as ILogger;
        private IGetDataForExcel _excelData = new GetDataForExcel();

        TblbLabelAttrData excel;
        IList<TblbLabelCase> lblCaseList;

        public static Int32 threadCount = 0;

        public Int32 ThreadCount
        {
            get { return DataSetToImage.threadCount; }
        }

        private Hashtable excelProcedureParams;

        public Hashtable ExcelProcedureParams
        {
            get { return excelProcedureParams; }
            set { excelProcedureParams = value; }
        }

        public void GoExportExcel()
        {
            excel = new TblbLabelAttrData();

            GoExportSecurityExcel();
            GoExportAccountExcel();
        }

        private void GoExportAccountExcel()
        {
            IList<TblbLabel> labelList = _dao.Query<TblbLabel>("TblbLabel.FindAllAccountExcelLabels", null);

            DataTable accountTable = _dao.QueryForTable("TblbAccountGraphy.FindAll", null).Tables[0];
            //DataTable accountTable = _dao.QueryForTable("TblbAccountGraphy.FindByACCOUNTCODE", 320000049061).Tables[0];

            ExcelToDatabase.threadCount += labelList.Count;

            foreach (TblbLabel lbl in labelList)
            {
                //Thread ta = new Thread(new ThreadStart(delegate()
                //{
                if (lbl.LABELTYPEID == 15 || lbl.LABELTYPEID == 16)
                {
                    DoExportExcel(accountTable, lbl.SECID, lbl.NAME, lbl.LABELTYPEID);
                }
                //}));
                //ta.Start();
            }
        }

        private void GoExportSecurityExcel()
        {
            //IList<TblbLabel> labelList = GetLabelList(Directory, ConfigFilePath);
            IList<TblbLabel> labelList = _dao.Query<TblbLabel>("TblbLabel.FindAllSecurityExcelLabels", null);

            DataTable stockTable = _dao.QueryForTable("SecurityInfo.FindAllStockForSnag", null).Tables[0];
            DataTable fundTable = _dao.QueryForTable("SecurityInfo.FindAllFundForSnag", null).Tables[0];
            DataTable warrantTable = _dao.QueryForTable("SecurityInfo.FindAllWarrantForSnag", null).Tables[0];
            DataTable bondTable = _dao.QueryForTable("SecurityInfo.FindAllBondForSnag", null).Tables[0];

            ExcelToDatabase.threadCount += labelList.Count;

            foreach (TblbLabel lbl in labelList)
            {
                //Thread ta = new Thread(new ThreadStart(delegate()
                //{
                if (lbl.LABELTYPEID == 19)
                {
                    DoExportExcel(lbl.SECID, lbl.NAME, lbl.LABELTYPEID, String.Empty, String.Empty, null, null);
                }
                else if (lbl.LABELTYPEID == 20)
                {
                    DoExportExcel(stockTable, lbl.SECID, lbl.NAME, lbl.LABELTYPEID);
                }
                else if (lbl.LABELTYPEID == 21)
                {
                    DoExportExcel(fundTable, lbl.SECID, lbl.NAME, lbl.LABELTYPEID);
                }
                else if (lbl.LABELTYPEID == 22)
                {
                    DoExportExcel(warrantTable, lbl.SECID, lbl.NAME, lbl.LABELTYPEID);
                }
                else if (lbl.LABELTYPEID == 23)
                {
                    DoExportExcel(bondTable, lbl.SECID, lbl.NAME, lbl.LABELTYPEID);
                }
                //}));
                //ta.Start();
            }
        }

        //[MethodImpl(MethodImplOptions.Synchronized)]
        private void DoExportExcel(Int64 labelID, String labelName, Int64 labelType, String secuCode, String secuName, Int16? secuType, Int64? accountCode)
        {
            try
            {
                InsertExcel(labelID, labelName, labelType, secuCode, secuName, secuType, accountCode);
            }
            catch (Exception ex)
            {
                _log.Error(DateTime.Now.ToString());
                _log.Error(Convert.ToString(labelID + "," + secuCode + "," + Convert.ToString(accountCode)));
                _log.Error(ex.Message);
                _log.Error(ex.StackTrace);
            }
            finally
            {
                ExcelToDatabase.threadCount--;
            }
        }

        //[MethodImpl(MethodImplOptions.Synchronized)]
        private void DoExportExcel(DataTable dataTable, Int64 labelID, String labelName, Int64 labelType)
        {
            try
            {
                foreach (DataRow dataInfo in dataTable.Rows)
                {
                    Int64? accountCode = 0;

                    String secuCode = String.Empty;
                    String secuName = String.Empty;
                    Int16? secuType = null;
                    try
                    {
                        if (dataTable.Columns.Contains("ACCOUNTCODE"))
                            accountCode = Convert.ToInt64(dataInfo["ACCOUNTCODE"]);

                        if (dataTable.Columns.Contains("ZQDM"))
                            secuCode = Convert.ToString(dataInfo["ZQDM"]);
                        if (dataTable.Columns.Contains("ZQJC"))
                            secuName = Convert.ToString(dataInfo["ZQJC"]);
                        if (dataTable.Columns.Contains("STOCKTYPE"))
                            secuType = Convert.ToInt16(dataInfo["STOCKTYPE"]);

                        excelProcedureParams["STOCKCODE"] = secuCode;
                        excelProcedureParams["ACCOUNTCODE"] = accountCode;

                        InsertExcel(labelID, labelName, labelType, secuCode, secuName, secuType, accountCode);
                    }
                    catch (Exception ex)
                    {
                        _log.Error(DateTime.Now.ToString());
                        _log.Error(Convert.ToString(labelID + "," + secuCode + "," + Convert.ToString(accountCode)));
                        _log.Error(ex.Message);
                        _log.Error(ex.StackTrace);

                        continue;
                    }
                }
            }
            finally
            {
                ExcelToDatabase.threadCount--;
            }
        }

        //[MethodImpl(MethodImplOptions.Synchronized)]
        private void InsertExcel(Int64 labelID, String labelName, Int64 labelType, String secuCode, String secuName, Int16? secuType, Int64? accountCode)
        {
            lblCaseList = _dao.Query<TblbLabelCase>("TblbLabelCase.FindByLABELID", labelID);
            foreach (TblbLabelCase lblCase in lblCaseList)
            {
                String title = String.Empty;
                if (labelType == 15 || labelType == 16)
                    title = Convert.ToString(accountCode) + "-";
                if (labelType == 20 || labelType == 21 || labelType == 22 || labelType == 23)
                    title = secuCode + "-";
                title += labelID + "-" + lblCase.SECID.ToString() + "-" + DateTime.Now.ToString("yyyy-MM-dd");
                String format = ".xls";
                String tempDirectory = Directory + "\\Temp\\";
                String fileName = tempDirectory + title + format;

                String procedureName = lblCase.SQLSTR;
                if (!procedureName.StartsWith("EXEC", StringComparison.OrdinalIgnoreCase))
                {
                    procedureName = "EXEC " + procedureName;
                }
                if (procedureName.Contains("@"))
                {
                    procedureName = procedureName.Substring(0, procedureName.IndexOf('@'));
                }

                Hashtable htParams = new Hashtable();
                //htParams["labelID"] = labelID;
                htParams["procedureName"] = procedureName;
                //foreach (DictionaryEntry de in excelProcedureParams)
                //{
                //    htParams.Add(de.Key, de.Value);
                //}
                if (labelType == 15 || labelType == 16)
                {
                    htParams["ACCOUNTCODE"] = excelProcedureParams["ACCOUNTCODE"];
                }
                else if (labelType == 19)
                {
                    htParams["JZRQ"] = excelProcedureParams["JZRQ"];
                }
                else if (labelType == 20 || labelType == 21 || labelType == 22 || labelType == 23)
                {
                    htParams["STOCKCODE"] = excelProcedureParams["STOCKCODE"];
                }

                DataSet dsSource = _excelData.GetDataSetByProcedure("ExcelDataProcedure.GetDataByProcedureName", htParams);
                if (dsSource.Tables[0].Columns.Contains("LABELID"))
                {
                    dsSource.Tables[0].Columns.Remove("LABELID");
                }
                ExcelExporter.ExportByOledb(dsSource, fileName);
                FileStream fs = File.OpenRead(fileName);
                Byte[] data = new Byte[fs.Length];
                fs.Read(data, 0, data.Length);
                fs.Close();

                excel.LABELID = labelID;
                excel.ACCOUNTCODE = accountCode;
                excel.STOCKCODE = secuCode;
                excel.STOCKNAME = secuName;
                excel.STOCKTYPE = secuType;
                excel.FILENAME = title;
                excel.EXT = format;
                excel.NR = data;
                excel.LASTEDITDATE = DateTime.Now;
                excel.OPERATIONDATE = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd"));
                _dao.Delete("TblbLabelAttrData.DeleteOne", excel);
                _dao.Insert("TblbLabelAttrData.Insert", excel);

                File.Delete(fileName);
            }
        }

        public void DeleteBeforeRecords(DateTime time)
        {
            //_dao.Delete("TblbLabelAttrData.DeleteBeforeRecords", time);
        }

        public ExcelExportConfig GetExcelExportConfig()
        {
            return ConfigLoader.LoadExcelExportConfig(Directory + ConfigFilePath);
        }

        public void SaveExcelExportConfig(ExcelExportConfig eec, IList<TblbLabel> labelList)
        {
            ConfigSaver.SaveExcelExportConfig(Directory + ConfigFilePath, eec, labelList);
        }

        public IList<ReportPeriod> GetReportPeriodList(Int32 periodCount)
        {
            IList<ReportPeriod> reportPeriodList = new List<ReportPeriod>();

            Int32 nowYear = DateTime.Now.Year;
            Int32 nowMonth = DateTime.Now.Month;
            Int32 nowDay = DateTime.Now.Day;
            Int32 reportYear = nowYear - 1;
            Int32 reportMonth = 12;
            Int32 reportDay = 31;

            if (nowMonth <= 6 && nowDay < 30)
            {
                reportYear = nowYear;
                reportMonth = 3;
            }
            else if (nowMonth <= 9 && nowDay < 30)
            {
                reportYear = nowYear;
                reportMonth = 6;
            }
            else if (nowMonth <= 12 && nowDay < 31)
            {
                reportYear = nowYear;
                reportMonth = 9;
            }
            else
            {
                reportYear = nowYear;
                reportMonth = 12;
            }

            reportDay = GetReportDay(reportMonth);

            for (Int32 i = 0; i < periodCount; i++)
            {
                ReportPeriod rp = new ReportPeriod();
                rp.DisplayPeriod = String.Format("{0}年{1}季", reportYear, GetReportPeriodCount(reportMonth));
                rp.ValueDate = String.Format("{0}-{1}-{2}", reportYear, reportMonth, reportDay);
                reportPeriodList.Add(rp);

                reportMonth -= 3;
                if (reportMonth <= 0)
                {
                    reportYear -= 1;
                    reportMonth = 12;
                    reportDay = GetReportDay(reportMonth);
                }
            }

            return reportPeriodList;
        }

        private Int32 GetReportDay(Int32 reportMonth)
        {
            Int32 reportDay = 30;
            switch (reportMonth)
            {
                case 3:
                case 12:
                    reportDay = 31;
                    break;
                case 6:
                case 9:
                    reportDay = 30;
                    break;
            }
            return reportDay;
        }

        private String GetReportPeriodCount(Int32 reportMonth)
        {
            String periodCount = String.Empty;
            switch (reportMonth)
            {
                case 3:
                    periodCount = "一";
                    break;
                case 6:
                    periodCount = "二";
                    break;
                case 9:
                    periodCount = "三";
                    break;
                case 12:
                    periodCount = "四";
                    break;
            }
            return periodCount;
        }
    }
}
